// Copyright (C) 1953-2022 NUDT
// Verilog module name - cpu_tx
// Version: V4.1.0.20221209
// Created:
//         by - fenglin
////////////////////////////////////////////////////////////////////////////
// Description:
//         
///////////////////////////////////////////////////////////////////////////

`timescale 1ns/1ps

module cpu_tx#(parameter local_module_id = 12'd0)
(
    i_clk  ,
    i_rst_n,
	
	iv_hcp_mid                            ,
	iv_os_cid                             ,
	
	iv_port_ptp_enabled                   ,    
    iv_measure_sync_state_report_enabled  ,
	
	i_sync_ok                             ,
	iv_sync_abnormal_cnt                  ,
	iv_offset                             ,
	i_sync_state_wr                       ,
    
    iv_csrateoffset_previousnode          ,
    i_csrateoffset_previousnode_wr        ,
	
	iv_fifo_data_count                    ,
    o_fifo_rden                           ,
    iv_fifo_rdata                         ,	

	ov_data                               ,
	o_data_wr                             
);

// I/O
// clk & rst
input                   i_clk;
input                   i_rst_n; 

input      [11:0]       iv_hcp_mid;
input      [11:0]       iv_os_cid ;
// pkt input                       
input      [31:0]       iv_port_ptp_enabled     ;
input                   iv_measure_sync_state_report_enabled;

input                   i_sync_ok                         ;
input	   [15:0]	    iv_sync_abnormal_cnt              ;
input	   [12:0]       iv_offset                         ;
input                   i_sync_state_wr                   ;

input	   [31:0]    	iv_csrateoffset_previousnode      ;
input                   i_csrateoffset_previousnode_wr    ;
// pkt output to NMA
input      [4:0]	    iv_fifo_data_count        ;
output reg	            o_fifo_rden      ;
input      [319:0]      iv_fifo_rdata     ;

output reg [8:0]        ov_data               ;
output reg              o_data_wr             ; 
//***************************************************
//               packet process
//***************************************************
reg                     r_sync_state_used                 ;

reg                     r_sync_ok                         ;
reg  	   [15:0]	    rv_sync_abnormal_cnt              ;
reg  	   [12:0]       rv_offset                         ;
reg  	   [31:0]    	rv_cumulativescaledrateoffset     ;
reg                     r_sync_state_wr                   ;
always @(posedge i_clk or negedge i_rst_n) begin
    if(!i_rst_n)begin
        r_sync_ok                            <= 1'b0 ;
        rv_sync_abnormal_cnt                 <= 16'b0;	
		rv_offset                            <= 13'b0;
		rv_cumulativescaledrateoffset        <= 32'b0;
		r_sync_state_wr                      <= 1'b0 ;                   
    end
    else begin
        if(i_sync_state_wr)begin	
			r_sync_ok                            <= i_sync_ok                    ;
			rv_sync_abnormal_cnt                 <= iv_sync_abnormal_cnt         ;	
			rv_offset                            <= iv_offset                    ;
			rv_cumulativescaledrateoffset        <= iv_csrateoffset_previousnode;
			r_sync_state_wr                      <= 1'b1              ;  
        end
        else if(r_sync_state_used)begin
            r_sync_state_wr                      <= 1'b0              ; 
        end
        else begin
            r_sync_state_wr                      <= r_sync_state_wr   ;  
        end		
    end
end	
//***************************************************
//               packet process
//***************************************************
reg       [15:0]              rv_sync_state_sequence           ;
reg       [15:0]              rv_measure_state_sequence        ;

reg       [10:0]              rv_byte_cnt            ;
reg       [5:0]               rv_ts_cnt              ;
reg       [2:0]               rv_ctx_state           ;
localparam      IDLE_S                            = 3'd0,
                REPORT_SYNC_STATE_S               = 3'd1,
                REPORT_MEASURE_STATE_S            = 3'd2,
                TRANSMIT_MEASURE_TIMESTAMPS_S     = 3'd3;
always @(posedge i_clk or negedge i_rst_n) begin
    if(!i_rst_n)begin
        rv_sync_state_sequence           <= 16'b0;
        rv_measure_state_sequence        <= 16'b0;	
		r_sync_state_used                <= 1'b0 ;
		rv_byte_cnt                      <= 8'b0 ;
		rv_ts_cnt                        <= 6'b0 ;
		o_fifo_rden                      <= 1'b0 ;
		
		ov_data                          <= 9'b0;
        o_data_wr                        <= 1'b0;
						                 
        rv_ctx_state                     <= IDLE_S;        
    end
    else begin
        case(rv_ctx_state)
            IDLE_S:begin
                r_sync_state_used         <= 1'b0 ;				
				rv_byte_cnt               <= 8'd0 ;
				rv_ts_cnt                 <= 6'b0 ;
				o_fifo_rden               <= 1'b0 ;
				ov_data                   <= 9'b0 ;
				o_data_wr                 <= 1'b0 ;			
				if(r_sync_state_wr)begin
					rv_sync_state_sequence    <= rv_sync_state_sequence + 1'b1;
					rv_ctx_state              <= REPORT_SYNC_STATE_S;  
				end
				else if((iv_fifo_data_count != 5'b0) && (iv_fifo_data_count >= (iv_port_ptp_enabled[0] + iv_port_ptp_enabled[1] + iv_port_ptp_enabled[2] + iv_port_ptp_enabled[3] + iv_port_ptp_enabled[4] + iv_port_ptp_enabled[5] + iv_port_ptp_enabled[6] + iv_port_ptp_enabled[7] + iv_port_ptp_enabled[8] + iv_port_ptp_enabled[9] + iv_port_ptp_enabled[10] + iv_port_ptp_enabled[11] + iv_port_ptp_enabled[12] + iv_port_ptp_enabled[13] + iv_port_ptp_enabled[14] + iv_port_ptp_enabled[15] + iv_port_ptp_enabled[16] + iv_port_ptp_enabled[17] + iv_port_ptp_enabled[18] + iv_port_ptp_enabled[19] + iv_port_ptp_enabled[20] + iv_port_ptp_enabled[21] + iv_port_ptp_enabled[22] + iv_port_ptp_enabled[23] + iv_port_ptp_enabled[24] + iv_port_ptp_enabled[25] + iv_port_ptp_enabled[26] + iv_port_ptp_enabled[27] + iv_port_ptp_enabled[28] + iv_port_ptp_enabled[29] + iv_port_ptp_enabled[30] + iv_port_ptp_enabled[31])))begin
					rv_measure_state_sequence <= rv_measure_state_sequence + 1'b1;	
					rv_ctx_state              <= REPORT_MEASURE_STATE_S;  
				end
				else begin
					rv_ctx_state    <= IDLE_S;  
				end                    
            end
			REPORT_SYNC_STATE_S:begin
                rv_byte_cnt     <= rv_byte_cnt + 1'b1;
				rv_ts_cnt       <= 6'b0 ;
				o_data_wr       <= 1'b1;
				case(rv_byte_cnt)
				    //dmac
				    8'd0:ov_data          <= {1'b1,8'h66};
                    8'd1:ov_data          <= {1'b0,8'h26};
					8'd2:ov_data          <= {1'b0,8'h62};
					8'd3:ov_data          <= {1'b0,iv_os_cid[11:4]     };
					8'd4:ov_data          <= {1'b0,iv_os_cid[3:0 ],4'h8};
					8'd5:ov_data          <= {1'b0,8'h02};
					//smac                
					8'd6:ov_data          <= {1'b0, 8'h66                                 };
					8'd7:ov_data          <= {1'b0, 8'h26                                 };
					8'd8:ov_data          <= {1'b0, 8'h62                                 };
					8'd9:ov_data          <= {1'b0, iv_hcp_mid[11:4]                      };
					8'd10:ov_data         <= {1'b0, iv_hcp_mid[3:0 ],local_module_id[11:8]};
					8'd11:ov_data         <= {1'b0, local_module_id[7:0  ]                };
					//eth type
					8'd12:ov_data         <= {1'b0,8'hFF};
					8'd13:ov_data         <= {1'b0,8'h01};
					//TSMP类型
					8'd14:ov_data         <= {1'b0,8'h06};
					//TSMP子类型
					8'd15:ov_data         <= {1'b0,8'h05};
					//OSM标识
					8'd16:ov_data         <= {1'b0,8'h00};
					//序列号
					8'd17:ov_data         <= {1'b0,rv_sync_state_sequence[15:8]};
					8'd18:ov_data         <= {1'b0,rv_sync_state_sequence[7:0 ]};
					//时间戳
					8'd19:ov_data         <= {1'b0,8'h00};
					8'd20:ov_data         <= {1'b0,8'h00};
					8'd21:ov_data         <= {1'b0,8'h00};
					//保留
					8'd22:ov_data         <= {1'b0,8'h00};
					8'd23:ov_data         <= {1'b0,8'h00};
					8'd24:ov_data         <= {1'b0,8'h00};
					8'd25:ov_data         <= {1'b0,8'h00};
					8'd26:ov_data         <= {1'b0,8'h00};
					8'd27:ov_data         <= {1'b0,8'h00};
					8'd28:ov_data         <= {1'b0,8'h00};
					8'd29:ov_data         <= {1'b0,8'h00};
					8'd30:ov_data         <= {1'b0,8'h00};
					8'd31:ov_data         <= {1'b0,8'h00};
					//有效位
					8'd32:ov_data         <= {1'b0,8'h01};
					//同步偏差异常计数器
					8'd33:ov_data         <= {1'b0,rv_sync_abnormal_cnt[15:8]};
                    8'd34:ov_data         <= {1'b0,rv_sync_abnormal_cnt[7:0 ]};
					//sync_ok,同步偏差
					8'd35:ov_data         <= {1'b0,r_sync_ok,2'b0,rv_offset[12:8]};
					8'd36:ov_data         <= {1'b0,rv_offset[7:0 ]};
					//累计放大频差
					8'd37:ov_data         <= {1'b0,rv_cumulativescaledrateoffset[31:24]};
					8'd38:ov_data         <= {1'b0,rv_cumulativescaledrateoffset[23:16]};
					8'd39:ov_data         <= {1'b0,rv_cumulativescaledrateoffset[15:8 ]};
					8'd40:begin
					    r_sync_state_used <= 1'b1;
						ov_data           <= {1'b0,rv_cumulativescaledrateoffset[7:0  ]};
				    end
					//填充
                    8'd41:begin
					    r_sync_state_used <= 1'b0;
						ov_data           <= {1'b0,8'h00};
					end
					8'd42:ov_data         <= {1'b0,8'h00};
					8'd43:ov_data         <= {1'b0,8'h00};				
                    8'd44:ov_data         <= {1'b0,8'h00};
					8'd45:ov_data         <= {1'b0,8'h00};
					8'd46:ov_data         <= {1'b0,8'h00};
					8'd47:ov_data         <= {1'b0,8'h00};
					8'd48:ov_data         <= {1'b0,8'h00};
					8'd49:ov_data         <= {1'b0,8'h00};
					8'd50:ov_data         <= {1'b0,8'h00};
					8'd51:ov_data         <= {1'b0,8'h00};
					8'd52:ov_data         <= {1'b0,8'h00};
					8'd53:ov_data         <= {1'b0,8'h00};
					8'd54:ov_data         <= {1'b0,8'h00};
					8'd55:ov_data         <= {1'b0,8'h00};
					8'd56:ov_data         <= {1'b0,8'h00};
					8'd57:ov_data         <= {1'b0,8'h00};
					8'd58:ov_data         <= {1'b0,8'h00};
					8'd59:begin                                             
					    ov_data         <= {1'b1,8'h00};
						rv_ctx_state    <= IDLE_S;
				    end  
                endcase				
			end
            REPORT_MEASURE_STATE_S:begin	           
                rv_byte_cnt     <= rv_byte_cnt + 1'b1;
				rv_ts_cnt       <= 6'b0 ;
				o_data_wr       <= 1'b1;
				case(rv_byte_cnt)
				    //dmac
				    8'd0:ov_data          <= {1'b1,8'h66};
                    8'd1:ov_data          <= {1'b0,8'h26};
					8'd2:ov_data          <= {1'b0,8'h62};
					8'd3:ov_data          <= {1'b0,iv_os_cid[11:4]     };
					8'd4:ov_data          <= {1'b0,iv_os_cid[3:0 ],4'h8};
					8'd5:ov_data          <= {1'b0,8'h02};
					//smac                
					8'd6:ov_data          <= {1'b0, 8'h66                                 };
					8'd7:ov_data          <= {1'b0, 8'h26                                 };
					8'd8:ov_data          <= {1'b0, 8'h62                                 };
					8'd9:ov_data          <= {1'b0, iv_hcp_mid[11:4]                      };
					8'd10:ov_data         <= {1'b0, iv_hcp_mid[3:0 ],local_module_id[11:8]};
					8'd11:ov_data         <= {1'b0, local_module_id[7:0  ]                };
					//eth type
					8'd12:ov_data         <= {1'b0,8'hFF};
					8'd13:ov_data         <= {1'b0,8'h01};
					//TSMP类型
					8'd14:ov_data         <= {1'b0,8'h06};
					//TSMP子类型
					8'd15:ov_data         <= {1'b0,8'h06};
					//OSM标识
					8'd16:ov_data         <= {1'b0,8'h00};
					//序列号
					8'd17:ov_data         <= {1'b0,rv_measure_state_sequence[15:8]};
					8'd18:ov_data         <= {1'b0,rv_measure_state_sequence[7:0 ]};
					//时间戳
					8'd19:ov_data         <= {1'b0,8'h00};
					8'd20:ov_data         <= {1'b0,8'h00};
					8'd21:ov_data         <= {1'b0,8'h00};
					//保留
					8'd22:ov_data         <= {1'b0,8'h00};
					8'd23:ov_data         <= {1'b0,8'h00};
					8'd24:ov_data         <= {1'b0,8'h00};
					8'd25:ov_data         <= {1'b0,8'h00};
					8'd26:ov_data         <= {1'b0,8'h00};
					8'd27:ov_data         <= {1'b0,8'h00};
					8'd28:ov_data         <= {1'b0,8'h00};
					8'd29:ov_data         <= {1'b0,8'h00};
					8'd30:ov_data         <= {1'b0,8'h00};
					8'd31:ov_data         <= {1'b0,8'h00};
					//端口PTP使能
					8'd32:ov_data         <= {1'b0,iv_port_ptp_enabled[31:24]};
					8'd33:ov_data         <= {1'b0,iv_port_ptp_enabled[23:16]};
                    8'd34:ov_data         <= {1'b0,iv_port_ptp_enabled[15:8 ]};
					8'd35:begin
					    ov_data         <= {1'b0,iv_port_ptp_enabled[7:0  ]};
						rv_ctx_state    <= TRANSMIT_MEASURE_TIMESTAMPS_S;
				    end
				endcase
			end
			TRANSMIT_MEASURE_TIMESTAMPS_S:begin
				rv_byte_cnt   <= rv_byte_cnt + 1'b1;
				if(rv_ts_cnt >= 6'd39)begin
				    rv_ts_cnt     <= 6'd0 ;
				end
				else begin
				    rv_ts_cnt     <= rv_ts_cnt + 1'b1 ;
				end
				case(rv_ts_cnt)
					//t1
					6'd0: ov_data         <= {1'b0,iv_fifo_rdata[79:72]};
					6'd1: ov_data         <= {1'b0,iv_fifo_rdata[71:64]};
					6'd2: ov_data         <= {1'b0,iv_fifo_rdata[63:56]};
					6'd3: ov_data         <= {1'b0,iv_fifo_rdata[55:48]};
					6'd4: ov_data         <= {1'b0,iv_fifo_rdata[47:40]};
					6'd5: ov_data         <= {1'b0,iv_fifo_rdata[39:32]};
					6'd6: ov_data         <= {1'b0,iv_fifo_rdata[31:24]};
					6'd7: ov_data         <= {1'b0,iv_fifo_rdata[23:16]};
                    6'd8: begin
					    //o_fifo_rden     <= 1'b1;
                        o_fifo_rden     <= 1'b0;
						ov_data         <= {1'b0,iv_fifo_rdata[15:8 ]};
					end
					6'd9: begin
					    o_fifo_rden     <= 1'b0;
					    ov_data         <= {1'b0,iv_fifo_rdata[7:0  ]};
					end
					//t2
					6'd10:ov_data         <= {1'b0,iv_fifo_rdata[159:152]};
					6'd11:ov_data         <= {1'b0,iv_fifo_rdata[151:144]};
					6'd12:ov_data         <= {1'b0,iv_fifo_rdata[143:136]};
					6'd13:ov_data         <= {1'b0,iv_fifo_rdata[135:128]};
					6'd14:ov_data         <= {1'b0,iv_fifo_rdata[127:120]};
					6'd15:ov_data         <= {1'b0,iv_fifo_rdata[119:112]};
					6'd16:ov_data         <= {1'b0,iv_fifo_rdata[111:104]};
					6'd17:ov_data         <= {1'b0,iv_fifo_rdata[103:96 ]};
                    6'd18:begin
					    //o_fifo_rden     <= 1'b1;
                        o_fifo_rden     <= 1'b0;
						ov_data         <= {1'b0,iv_fifo_rdata[95:88 ]};
					end
					6'd19:begin
					    o_fifo_rden     <= 1'b0;
					    ov_data         <= {1'b0,iv_fifo_rdata[87:80 ]};
					end	
					//1st-t3
					6'd20:ov_data         <= {1'b0,iv_fifo_rdata[239:232]};
					6'd21:ov_data         <= {1'b0,iv_fifo_rdata[231:224]};
					6'd22:ov_data         <= {1'b0,iv_fifo_rdata[223:216]};
					6'd23:ov_data         <= {1'b0,iv_fifo_rdata[215:208]};
					6'd24:ov_data         <= {1'b0,iv_fifo_rdata[207:200]};
					6'd25:ov_data         <= {1'b0,iv_fifo_rdata[199:192]};
					6'd26:ov_data         <= {1'b0,iv_fifo_rdata[191:184]};
					6'd27:ov_data         <= {1'b0,iv_fifo_rdata[183:176 ]};
                    6'd28:begin
					    //o_fifo_rden     <= 1'b1;
                        o_fifo_rden     <= 1'b0;
						ov_data         <= {1'b0,iv_fifo_rdata[175:168 ]};
					end
					6'd29:begin
					    o_fifo_rden     <= 1'b0;
					    ov_data         <= {1'b0,iv_fifo_rdata[167:160 ]};
					end	
					//1st-t4
					6'd30:ov_data         <= {1'b0,iv_fifo_rdata[319:312]};
					6'd31:ov_data         <= {1'b0,iv_fifo_rdata[311:304]};
					6'd32:ov_data         <= {1'b0,iv_fifo_rdata[303:296]};
					6'd33:ov_data         <= {1'b0,iv_fifo_rdata[295:288]};
					6'd34:ov_data         <= {1'b0,iv_fifo_rdata[287:280]};
					6'd35:ov_data         <= {1'b0,iv_fifo_rdata[279:272]};
					6'd36:ov_data         <= {1'b0,iv_fifo_rdata[271:264]};
					6'd37:ov_data         <= {1'b0,iv_fifo_rdata[263:256 ]};
                    6'd38:begin
					    o_fifo_rden     <= 1'b1;
						ov_data         <= {1'b0,iv_fifo_rdata[255:248 ]};
					end
					6'd39:begin
					    o_fifo_rden     <= 1'b0;
					    ov_data[7:0]    <= iv_fifo_rdata[247:240 ];
						if(iv_fifo_data_count == 5'd1)begin
						    ov_data[8]    <= 1'b1;
                            rv_ctx_state  <= IDLE_S;
						end
						else begin
						    ov_data[8]    <= 1'b0;
                            rv_ctx_state  <= TRANSMIT_MEASURE_TIMESTAMPS_S;
						end
					end
                    default:begin
                        o_fifo_rden     <= 1'b0;
						rv_ctx_state    <= TRANSMIT_MEASURE_TIMESTAMPS_S;
                    end					
                endcase
            end	          
            default:begin
                r_sync_state_used         <= 1'b0 ;				
				rv_byte_cnt               <= 8'd0 ;
				rv_ts_cnt                 <= 6'b0 ;
				o_fifo_rden               <= 1'b0 ;
				ov_data                   <= 9'b0 ;
				o_data_wr                 <= 1'b0 ;				
				rv_ctx_state              <= IDLE_S;  
            end
        endcase
    end
end
endmodule